//
// Created by LiuYou on 2021/10/22.
//

#include <unistd.h>
#include <cstdio>
#include <cstdlib>
#include <cerrno>
#include <csignal>
#include <fcntl.h>
#include "MyTbf.hpp"


//static const int CHARACTER_PER_SEC{10};
//static const int BURST{100};
static const int CHARACTER_PER_SEC{1024};
static const int BURST{1024 * 10};

static const int BUF_SIZE{1024};


/**
 * @brief 使用自己设计的令牌桶的库。
 */
int main(int argc, char** argv) {
    if (argc < 2) {
        fprintf( stderr, "Usage: ...\n" );
        exit( 1 );
    }

    Tbf* aTbf = tbfInit( CHARACTER_PER_SEC, BURST );
    if (aTbf == nullptr) {
        fprintf( stderr, "tbfInit();调用失败了！\n" );
        exit( 1 );
    }


    int srcFd{};
    do {
        srcFd = open( argv[1], O_RDONLY );
        if (srcFd < 0) {
            if (errno != EINTR) {
                perror( "open()" );
                exit( 1 );
            }
        }
    } while (srcFd < 0);

    int desFd{1};

    char buf[BUF_SIZE]{};
    int pos{};
    for (;;) {

        int tokens = fetchToken( aTbf, BUF_SIZE );


        ssize_t readBytes{};
        while ((readBytes = read( srcFd, buf, tokens )) < 0) {
            if (errno == EINTR) {
                continue;
            }
            perror( "read()" );
            break;
        }
        if (readBytes == 0) {
            break;
        }

        if (tokens - readBytes > 0) {
            returnToken( aTbf, tokens - (int) readBytes );
        }


        pos = 0;
        // 坚持写够readBytes个字节
        while (readBytes > 0) {
            ssize_t writeBytes = write( desFd, buf + pos, readBytes );
            if (writeBytes < 0) {
                if (errno == EINTR) {
                    continue;
                }
                perror( "write()" );
                close( srcFd );
                exit( 1 );
            }
            // 这里很精妙
            readBytes -= writeBytes;
            pos += (int) writeBytes;
        }
    }


    close( srcFd );

    tbfDestroy( aTbf );

    return 0;
}

